/*
 * Pidgin Personal Bar
 * 
 * Copyright 2008 Craig Harding <craigwharding@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#define PURPLE_PLUGINS

#ifndef G_GNUC_NULL_TERMINATED
#	if     __GNUC__ >= 4
#		define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__))
#	else
#		define G_GNUC_NULL_TERMINATED
#	endif
#endif

#include <glib.h>
#include <gmodule.h>
#include <string.h>
#include "plugin.h"
#include "signals.h"
#include "version.h"

#include "gtkblist.h"
#include "gtkstatusbox.h"
#include "gtkplugin.h"
#include "gtkprefs.h"
#include "prpl.h"
#include "request.h"
#include "debug.h"
#include "gtkutils.h"

#ifdef _WIN32
	#include "win32dep.h"
#endif

#define PLUGIN_ID     			"gtk-charding-personalbar"
#define PLUGIN_VERSION			"0.1svn"
#define PLUGIN_NAME				"Pidgin Personal Bar"
#define PLUGIN_AUTHOR			"Craig Harding <craigwharding@gmail.com>"
#define PLUGIN_WEBSITE			"http://code.google.com/p/pidgin-personalbar/"

#define PLUGIN_ID_PB_WIDGET		"personalbar"
#define PLUGIN_ID_DN_WIDGET		"displayname"
#define PLUGIN_ID_DNL_WIDGET		"display_name_label"
#define PLUGIN_ID_STATUS_LABEL	"status_label"
#define PLUGIN_ID_PM_LABEL			"personalmsg_label"
#define PLUGIN_ID_PM_ENTRY			"personalmsg_entry"

#define MU_BIG_BOLD				"<big><b>%s</b></big>"
#define MU_DISPLAY_NAME			"<span font_size=\"medium\" foreground=\"black\" background=\"#eaeaea\"><b>%s</b></span>"
#define MU_DISPLAY_NAME_HOVER	"<span font_size=\"medium\" foreground=\"blue\" background=\"#eaeaea\"><b>%s</b></span>"
#define MU_PERSONAL_MSG			"<span background=\"#eaeaea\"><small>%s</small></span>"
#define MU_PERSONAL_MSG_HOVER	"<span foreground=\"blue\" background=\"#eaeaea\"><small><u>%s</u></small></span>"
#define MU_STATUS					"<span foreground=\"black\" size=\"small\"> %s</span>"

#define DISPLAY_NAME_EMPTY		"<Display Name>"
#define PERSONAL_MSG_EMPTY		"<Type a personal message>"

#define MAIN_PACKING_SIZE		5	
#define ICON_PACKING_SIZE		5	
#define PM_MAX_LENGTH			15

static const char *pref_hide_status_bar	= "/plugins/gtk/charding/personalbar/hide_status_bar";
static const char *pref_display_name		= "/plugins/gtk/charding/personalbar/display_name";
static const char *pref_personal_msg		= "/plugins/gtk/charding/personalbar/personal_msg";
static const char *pref_blist_width			= PIDGIN_PREFS_ROOT "/blist/width";

static GtkWidget *
get_pb_widget(PidginBuddyList *gtkblist) {
	GtkWidget *pb;

	pb = g_object_get_data(G_OBJECT(gtkblist->vbox), PLUGIN_ID_PB_WIDGET);
	if (pb != NULL) return pb;
	else return NULL;
}

static GtkLabel *
get_dn_label(GtkWidget *pb) {
	GtkLabel *widget =  g_object_get_data(G_OBJECT(pb), PLUGIN_ID_DN_WIDGET);
	return widget;

}

static GtkButton *
get_status_label(GtkWidget *pb) {
	GtkButton *sl =  g_object_get_data(G_OBJECT(pb), PLUGIN_ID_STATUS_LABEL);
	return sl;
}

static GtkLabel *
get_pm_label(GtkWidget *pb) {
	GtkLabel *pml = g_object_get_data(G_OBJECT(pb), PLUGIN_ID_PM_LABEL);
	return pml;
}

static GtkEntry *
get_pm_entry(GtkWidget *pb) {
	GtkEntry *pme = g_object_get_data(G_OBJECT(pb), PLUGIN_ID_PM_ENTRY);
	return pme;
}

/* Updates the display name label in the personal bar */
void 
update_display_name(const gchar *entry) {
	GtkWidget *pb_widget;
	GtkLabel *display_name_label;
	char *markup;

	pb_widget = get_pb_widget(PIDGIN_BLIST(purple_get_blist()));
	display_name_label = get_dn_label(pb_widget);

	purple_debug_info(PLUGIN_ID, "update_display_name started with entry as: %s\n", entry);
	if (strcmp(entry, "")) {
		purple_debug_info(PLUGIN_ID, "update_display_name: entry: %s\n", entry);
		/* mark it up and change it */
		markup = g_markup_printf_escaped (MU_DISPLAY_NAME, entry);
		gtk_label_set_markup (GTK_LABEL(display_name_label), markup);
		/* Update the display name pref */
		purple_prefs_set_string(pref_display_name, entry);
	}
	else if (entry == NULL) {
		purple_debug_error(PLUGIN_ID, "update_display_name: entry is NULL\n");
	}
	else {
		purple_debug_info(PLUGIN_ID, "update_display_name: Entry is empty\n");
		purple_prefs_set_string(pref_display_name, "");
		markup = g_markup_printf_escaped(MU_DISPLAY_NAME, DISPLAY_NAME_EMPTY);
		gtk_label_set_markup(GTK_LABEL(display_name_label), markup);
		//gtk_button_set_label (GTK_BUTTON (display_name_button), DISPLAY_NAME_EMPTY);
	}




}

void
change_jabber_nick(PurpleConnection *gc, const char *nick) {

	PurpleAccount *account;
	const char *id;

	/* http://xmpp.org/extensions/xep-0172.html#manage */
	/* XML stanza format to change xmpp nickname (PEP) 
		<iq from='narrator@moby-dick.lit/pda' type='set' id='pub1'>
			<pubsub xmlns='http://jabber.org/protocol/pubsub'>
				<publish node='http://jabber.org/protocol/nick'>
					<item>
					<nick xmlns='http://jabber.org/protocol/nick'>CallMeIshmael</nick>
					</item>
				</publish>
			</pubsub>
		</iq>

		Or use Pubsub Node
		<iq from='narrator@moby-dick.lit/pda' to='pubsub.mody-dick.lit' type='set' id='pub2'>
			<pubsub xmlns='http://jabber.org/protocol/pubsub'>
				<publish node='841f3c8955c4c41a0cf99620d78a33b996659ded'>
					<item>
					<nick xmlns='http://jabber.org/protocol/nick'>CallMeIshmael</nick>
					</item>
				</publish>
			</pubsub>
		</iq>
	*/

	account = purple_connection_get_account(gc);
	id = purple_account_get_protocol_id(account);

	xmlnode *iq, *pubsub, *publish, *nicknode;

	iq = xmlnode_new("iq");
	xmlnode_set_attrib(iq, "from", g_strdup_printf("%s%s", purple_account_get_username(account), "laptop"));
//			 resource_name = jabber_get_resource(jbi->jid);
	xmlnode_set_attrib(iq, "type", "set");
	xmlnode_set_attrib(iq, "id", "pub1");
	pubsub = xmlnode_new("pubsub");
	xmlnode_set_attrib(pubsub, "xmlns", "http://jabber.org/protocol/pubsub");
	publish = xmlnode_new("publish");
	xmlnode_set_attrib(publish,"node","http://jabber.org/protocol/nick");
	nicknode = xmlnode_new_child(xmlnode_new_child(publish, "item"), "nick");
	xmlnode_set_namespace(nicknode, "http://jabber.org/protocol/nick");
	if (nick) xmlnode_insert_data(nicknode, nick, -1);
	xmlnode_insert_child(pubsub, publish);
	xmlnode_insert_child(iq, pubsub);		

	if (gc != NULL) {
		purple_debug_info(PLUGIN_ID, "Sending jabber info: %s\n", xmlnode_to_formatted_str(iq,NULL));
		//jabber_send(gc->proto_data, iq);
		purple_debug_info(PLUGIN_ID, "Finished sending jabber info\n");
	}
}

/* callback for when setting alias (purple_account_set_public_alias) does not work */
void
public_alias_failure_cb(PurpleAccount *account, const char *error) {
	purple_debug_info(PLUGIN_ID, "%s does not support server side aliases/nicks\n", purple_account_get_protocol_id(account));
}

void
change_msn_nick(PurpleConnection *gc, const char *nick) {
	purple_account_set_public_alias(gc->account, nick, NULL, public_alias_failure_cb);
}

/* From felipec on pidgin-dev mailing list */
static void
serv_set_alias (PurpleConnection *gc, const char *alias) {
	PurplePlugin *prpl;
	void (*set_alias) (PurpleConnection *gc, const char *alias);

	if (!gc)
	return;

	prpl = purple_connection_get_prpl (gc);
	if (!g_module_symbol (prpl->handle, "set_alias", (void *) &set_alias))
	return;

	set_alias (gc, alias);
}


void
change_msn_pecan_nick(PurpleConnection *gc, const char *nick) {
	purple_debug_error(PLUGIN_ID, "calling serv_set_alias\n");
	serv_set_alias(gc, nick);
}

/* Change display name for all accts - used 
 * after display name label is clicked and 
 * purple_request_dialog receives input */
void
display_name_change_all_accts(PurpleConnection *gc, const char *nick) {
	GList *pb_accts;
	PurpleAccount *account;
	const char *id;

	purple_debug_info(PLUGIN_ID, "display_name_change_all_accts: Changing display name for all accts\n");
	for (pb_accts = purple_accounts_get_all_active(); pb_accts != NULL; pb_accts = pb_accts->next) {
		account = pb_accts->data;
		if (purple_account_is_connected(account)) {
			/* msn-pecan is an exception for the p_a_set_public_alias rule */
			id = purple_account_get_protocol_id(account);
	   	if (!strcmp(id, "prpl-msn-pecan")) {
				purple_debug_info(PLUGIN_ID, "display_name_change_all_accts(): Changing MSN PECAN (%s) DN to: %s\n", id, nick);			
				change_msn_pecan_nick(account->gc, nick);
			}
			else if (!strcmp(id, "prpl-jabber")) {
				purple_debug_info(PLUGIN_ID, "display_name_change_all_accts(): changing JABBER (%s) DN to: %s\n", id, nick);			
				change_jabber_nick(account->gc, nick);	
			}	
			else purple_account_set_public_alias(account, nick, NULL, public_alias_failure_cb); 
		}
		else purple_debug_info(PLUGIN_ID, "display_name_change_all_accts: Account not connected\n"); 
	
		/* Update the personal bar display name */
		/* Note: Set display name in prefs.xml */
	}
	/* Update the personal bar display name */
	update_display_name(nick);
}


/* Callback for when an individual acct signs on (signed_on_cb) */
void 
display_name_change_id_cb(PurpleConnection *gc, const char *nick) {
	PurpleAccount *account;
	//gc = NULL;
	//GList *pb_accts;
	const char *id;

	purple_debug_info(PLUGIN_ID, "display_name_change_id_cb: Changing display name to: %s\n", nick);
	account = purple_connection_get_account(gc);
	id = purple_account_get_protocol_id(account);
	if (!strcmp(id, "prpl-msn-pecan")) {
			purple_debug_info(PLUGIN_ID, "display_name_change_id_cb(): Changing MSN PECAN DN: %s\n", id);			
			change_msn_pecan_nick(gc, nick);
		}
	else if (!strcmp(id, "prpl-jabber")) {
			purple_debug_info(PLUGIN_ID, "display_name_change_all_accts(): changing JABBER (%s) DN to: %s\n", id, nick);			
			change_jabber_nick(gc, nick);	
	}
	else {
		purple_account_set_public_alias(account, nick, NULL, public_alias_failure_cb);
	}
	purple_debug_info(PLUGIN_ID, "Changing display name to: %s\n", nick);
	/* Update the personal bar display name */
	update_display_name(nick);
	/* Note: Set display name in prefs.xml */
}

/* Callback for when the display name button is clicked */
gboolean
on_display_name_focus_cb (GtkWidget *widget, GdkEventFocus *event, gpointer user_data) {

	purple_debug_error(PLUGIN_ID, "display_name_button Got focus!\n");
	const char *display_name;
	display_name = purple_prefs_get_string(pref_display_name);

	// **Note to add: If all accts Offline, then do not show the input dialog
	purple_request_input(/*gc*/NULL, NULL, ("Set your friendly name."),
				("This is the name that other buddies will see you as."),
				display_name/*purple_connection_get_display_name(gc)*/, FALSE, FALSE, NULL,
				("OK"), G_CALLBACK(display_name_change_all_accts),
				("Cancel"), NULL,
				NULL, NULL, NULL,
				NULL);
	
	return FALSE;
}

/* When hovering over the display name change the 
	highlighting and the pointer to a 'hand' pointer */
gboolean
on_display_name_hover_cb (GtkWidget *widget, GdkEventFocus *event, gpointer user_data) {
	gchar *markup;
	PidginBuddyList *gtkblist = PIDGIN_BLIST(purple_get_blist());
	GtkLabel *dn_label = get_dn_label(get_pb_widget(gtkblist));

	/* When hovering, change markup and pointer type */
	if (event->type == GDK_ENTER_NOTIFY) {
		markup = g_markup_printf_escaped (MU_DISPLAY_NAME_HOVER, gtk_label_get_text(dn_label));
		gtk_label_set_markup (GTK_LABEL(dn_label), markup);
		pidgin_set_cursor(gtkblist->window, GDK_HAND2);
	}
	/* When leaving, change it back to normal */
		else if (event->type == GDK_LEAVE_NOTIFY) {
		markup = g_markup_printf_escaped (MU_DISPLAY_NAME, gtk_label_get_text(dn_label));
		gtk_label_set_markup (GTK_LABEL(dn_label), markup);
		pidgin_clear_cursor(gtkblist->window);
	}
	return FALSE;
}

/* When hovering over the personal message, change the highlighting 
	and underlinging of the text. Also change the pointer to a 'hand' pointer */
gboolean
on_personal_msg_hover_cb (GtkWidget *widget, GdkEventFocus *event, gpointer user_data) {
	gchar *markup;
	PidginBuddyList *gtkblist = PIDGIN_BLIST(purple_get_blist());
	GtkLabel *pm_label = get_pm_label(get_pb_widget(gtkblist));

	/* When hovering, change markup and pointer type */
	if (event->type == GDK_ENTER_NOTIFY) {
		markup = g_markup_printf_escaped (MU_PERSONAL_MSG_HOVER, gtk_label_get_text(pm_label));
		gtk_label_set_markup (GTK_LABEL(pm_label), markup);
		pidgin_set_cursor(gtkblist->window, GDK_HAND2);
	}
	/* When leaving, change it back to normal */
	else if (event->type == GDK_LEAVE_NOTIFY) {
		markup = g_markup_printf_escaped (MU_PERSONAL_MSG, gtk_label_get_text(pm_label));
		gtk_label_set_markup (GTK_LABEL(pm_label), markup);
		pidgin_clear_cursor(gtkblist->window);
	}
	return FALSE;
}

/* Callback for when the status button is clicked */
gboolean
on_status_button_clicked_cb (GtkWidget *widget, GdkEventFocus *event, gpointer user_data) {

	// TODO: Show the status menu from the bottom pidgin status
	return TRUE;
}

// Do I need this?
gboolean
on_dn_box_focus_cb (GtkWidget *widget, GdkEventFocus *event, gpointer user_data) {
 
	purple_debug_info(PLUGIN_ID, "dn_box got focus!\n");
//	gtk_widget_grab_focus(gtkwidget);
	return TRUE;
}

/* Update's the personal message in the personal bar */
void
update_psm_label(const char *entry) {
	char *markup;
	gint pm_label_width, pm_label_height;
	char *pref = PIDGIN_PREFS_ROOT "/blist/width";

	PidginBuddyList *gtkblist = PIDGIN_BLIST(purple_get_blist());
	GtkLabel *psm_label = get_pm_label(get_pb_widget(gtkblist));
	markup = g_markup_printf_escaped (MU_PERSONAL_MSG, entry);
	gtk_label_set_markup (GTK_LABEL(psm_label), markup);
	
	gtk_widget_get_size_request(GTK_WIDGET(psm_label), &pm_label_width, &pm_label_height);
	//gtk_widget_set_size_request(hbox, purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-12, -1);
if (purple_prefs_get_int(pref)-50 < pm_label_width) {
		gtk_widget_set_size_request(GTK_WIDGET(psm_label), purple_prefs_get_int(pref)-50, -1);
		/* Not changing the psm_entry as it looks better if kept to width of buddy list */
 	}
	
	gtk_widget_set_tooltip_text(GTK_WIDGET(psm_label), entry);
}

/* Callback for the pidgin input request dialog to change the personal message */
void
psm_change_cb(PurpleConnection *gc, const char *entry) {
	PidginStatusBox *statusbox;
	gchar *imhtml_text;

	/* Set the PSM string on status line */
	statusbox = PIDGIN_STATUS_BOX(pidgin_blist_get_default_gtk_blist()->statusbox);
	imhtml_text = gtk_imhtml_get_markup(GTK_IMHTML(statusbox->imhtml));
	purple_debug_info(PLUGIN_ID, "imhtml_text was: %s, now: %s\n", imhtml_text, entry);
	if (!statusbox->imhtml_visible) statusbox->imhtml_visible = TRUE;

	/* If the user returns an empty string then set the default
	 * string in the label, but give the imhtml and pref an
	 * empty value */
	if (!strcmp(entry, "")) {
		purple_debug_info(PLUGIN_ID, "psm_change_cb: Updating PM to default value\n");
		/* Set default <> message in label but not in status box imhtml or pref */
		update_psm_label(PERSONAL_MSG_EMPTY);
		/* Set the statusbox imhtml which sets the personal message for us easily */
		gtk_text_buffer_set_text(GTK_IMHTML(statusbox->imhtml)->text_buffer, entry, -1);
		purple_prefs_set_string(pref_personal_msg, entry);
	}
	else if (entry != NULL && strcmp(entry, "")) {
		purple_debug_info(PLUGIN_ID, "psm_change_cb: Updating PM\n");
		/* Set the statusbox imhtml which sets the personal message for us easily */
		gtk_text_buffer_set_text(GTK_IMHTML(statusbox->imhtml)->text_buffer, entry, -1);//strlen(entry));
		purple_debug_info(PLUGIN_ID, "Updating psm label\n");
		/* Update the personal message label */
		update_psm_label(entry);
		/* Update the personal message pref string */
		purple_prefs_set_string(pref_personal_msg, entry);

	}

}


/* 
	Change (hide/show) the personal message label to a text box entry and populate
	the text box with the existing personal message 
*/
gboolean
on_personal_msg_focus_cb (GtkWidget *widget, GdkEventFocus *event, gpointer user_data) {

	PidginBuddyList *gtkblist = PIDGIN_BLIST(purple_get_blist());
	GtkLabel *pm_label = get_pm_label(get_pb_widget(gtkblist));
	GtkEntry *pm_entry = get_pm_entry(get_pb_widget(gtkblist));
	purple_debug_info(PLUGIN_ID, "Hiding label, showing entry\n");
	gtk_widget_hide (GTK_WIDGET(pm_label));
	gtk_widget_show (GTK_WIDGET(pm_entry));
	char *pmsg = strdup (gtk_label_get_text (GTK_LABEL (pm_label)));
	gtk_entry_set_text (GTK_ENTRY (pm_entry), strcmp (pmsg, PERSONAL_MSG_EMPTY) ? pmsg : "");
	gtk_widget_grab_focus (GTK_WIDGET(pm_entry));
	return TRUE;
}

/* Change the personal message text box back to the label */
gboolean
on_personal_entry_focus_out_cb(GtkWidget *widget, GdkEventFocus *event, gpointer user_data) { 

	PidginBuddyList *gtkblist = PIDGIN_BLIST(purple_get_blist());
	GtkLabel *pm_label = get_pm_label(get_pb_widget(gtkblist));
	GtkEntry *pm_entry = get_pm_entry(get_pb_widget(gtkblist));
	const gchar *text;

	purple_debug_info(PLUGIN_ID, "focus out event\n");
	text = gtk_entry_get_text(GTK_ENTRY(widget));
	update_psm_label(text);
	psm_change_cb(NULL, text);
	gtk_widget_hide(GTK_WIDGET(pm_entry));
	gtk_widget_show(GTK_WIDGET(pm_label));

	return FALSE;

}

/* Catch different keystrokes while editing the personal status message */
gboolean
on_personal_entry_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data)   {
	// See <gdk/gdkkeysyms.h>
	#define EnterKey 65293
	#define EscapeKey 65307
	const gchar *text;

	PidginBuddyList *gtkblist = PIDGIN_BLIST(purple_get_blist());
	if (event->keyval == EnterKey) {
		purple_debug_info("ExtPrefs", "Enter key keyval: %x, str: %s\n", event->keyval, event->string);
		GtkLabel *pm_label = get_pm_label(get_pb_widget(gtkblist));
		GtkEntry *pm_entry = get_pm_entry(get_pb_widget(gtkblist));
		text = gtk_entry_get_text(GTK_ENTRY(widget));
		update_psm_label(text);
		psm_change_cb(NULL, text);
		gtk_widget_hide(GTK_WIDGET(pm_entry));
		gtk_widget_show(GTK_WIDGET(pm_label));
	}
	else if (event->keyval == EscapeKey) {
		purple_debug_info("ExtPrefs", "Escape key keyval: %x, str: %s\n", event->keyval, event->string);
		if (gtk_widget_get_can_focus(gtkblist->vbox)) {
			purple_debug_info(PLUGIN_ID, "gtkblist->window can get focus\n");
		}
		else {
			purple_debug_info(PLUGIN_ID, "gtkblist->window CAN'T get focus\n");
			gtk_widget_set_can_focus(gtkblist->vbox, TRUE);
		}
		gtk_widget_grab_focus(GTK_WIDGET(gtkblist->vbox));
	}

	return FALSE;
}

const char *
get_statusbox_text() {
	PidginStatusBox *statusbox;
	GtkTextBuffer *buffer;
	GtkTextIter start, end;
	const char /**display_name, *status, *personal_msg,*/ *statusbox_imhtml; 
	int buffer_count;

	purple_debug_info(PLUGIN_ID, "get_statusbox_text starting\n");
	statusbox = PIDGIN_STATUS_BOX(pidgin_blist_get_default_gtk_blist()->statusbox);
	buffer = GTK_IMHTML(statusbox->imhtml)->text_buffer;
	buffer_count = gtk_text_buffer_get_char_count(buffer);
	/* Need to check that buffer is not empty, otherwise iter_at_offset crashes plugin */
	if (buffer_count > 0 && buffer != NULL) {
		purple_debug_info(PLUGIN_ID, "get_statusbox_text: buffer_count = %i\n", buffer_count);
		gtk_text_buffer_get_iter_at_offset (buffer, &start, 0);
		gtk_text_buffer_get_iter_at_offset (buffer, &end, -1);
		statusbox_imhtml = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
		return statusbox_imhtml;
	}
	else return "";
}

/* Is the status box visible? */
static gboolean 
status_box_visible(PidginBuddyList *gtkblist) {
	gboolean visible;
	if (gtkblist != NULL && GTK_IS_WINDOW(gtkblist->window)) {
		g_object_get(G_OBJECT(gtkblist->statusbox), "visible", &visible, NULL);
	} else {
		visible = FALSE;
	}	
	return visible;
}

void
insert_personal_bar(PidginBuddyList *gtkblist/*, const char *display_name, const char *status*/) {
	GtkWidget *vbox, *status_button, *hbox, *dn_box;
	GtkWidget *display_name_label, *pm_label, *pm_entry;
	GtkEventBox *pm_eb;
	GdkColor color;
	const char *display_name, *personal_msg, *statusbox_text; 
	GtkTreePath *path;
	GtkTreeIter iter;
	//PidginStatusBoxItemType type;
	char *text, *type, *data;
	GString *status; 
	gint pm_label_width, pm_label_height;

	vbox = gtk_vbox_new (FALSE, 2);
	hbox = gtk_hbox_new (FALSE, 2);
	dn_box = gtk_hbox_new (FALSE, 2);
	gtk_widget_show(hbox);
	gtk_widget_show(vbox);
	gtk_widget_show(dn_box);

	/* Set the main hbox a little smaller than the buddy list window */
	gtk_widget_set_size_request(GTK_WIDGET(hbox), purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-12, -1);
	gtk_box_pack_start (GTK_BOX (gtkblist->vbox), hbox, FALSE, FALSE, MAIN_PACKING_SIZE);
	gtk_box_reorder_child(GTK_BOX (gtkblist->vbox), hbox, 0);

	g_object_set_data(G_OBJECT(gtkblist->vbox), PLUGIN_ID_PB_WIDGET, hbox);


	/* 
	 * User icon 
	 *
	 * NOTE: Fix scaling to correctly scale it's size
	 */
	PidginStatusBox *statusbox = PIDGIN_STATUS_BOX(gtkblist->statusbox);
	int icon_size = statusbox->icon_size;
	GdkPixbuf *buddy_icon = statusbox->buddy_icon;

	purple_debug_info(PLUGIN_ID, "icon size: %d\n", icon_size);

	if (statusbox->buddy_icon != NULL) {
		purple_debug_info(PLUGIN_ID, "buddy_icon not NULL\n");
		GdkPixbuf *buddy_icon_scaled = gdk_pixbuf_scale_simple(buddy_icon, icon_size, icon_size, GDK_INTERP_BILINEAR);
		GtkWidget *buddy_icon_widget = gtk_image_new_from_pixbuf(buddy_icon_scaled);
		gtk_widget_show(buddy_icon_widget);
		gtk_box_pack_start(GTK_BOX (hbox), GTK_WIDGET(buddy_icon_widget), FALSE, FALSE, ICON_PACKING_SIZE);
	}

	char *markup;

	/*
	 * Display Name Label
	 *
	 */
	
	GtkEventBox *eb;
	display_name_label = gtk_label_new(NULL);
	eb = gtk_event_box_new();
	gtk_widget_show(GTK_WIDGET(eb));
	gtk_container_add(GTK_CONTAINER(eb), GTK_WIDGET(display_name_label));
	gtk_event_box_set_above_child(GTK_EVENT_BOX(eb), FALSE);
	gtk_widget_set_events(GTK_WIDGET(eb), GDK_BUTTON_PRESS_MASK);
	//gtk_container_set_border_width(eb, 0);
	//colormap = gdk_colormap_get_system  for default gdkcolormap
	//colormap->colors is of type gdkcolor
	//GdkColor color;
	
	gdk_color_parse ("#eaeaea", &color);
	gtk_widget_modify_bg (GTK_WIDGET(eb), GTK_STATE_NORMAL, &color);
	
	display_name = purple_prefs_get_string(pref_display_name);
	if (!strcmp(display_name, "")) {
		purple_debug_info(PLUGIN_ID, "insert_personal_bar: stored display name is empty, using <Display Name> for label\n");
		display_name = "<Display Name>";
	}
	markup = g_markup_printf_escaped (MU_DISPLAY_NAME, display_name);
	gtk_label_set_markup (GTK_LABEL(display_name_label), markup);
	gtk_widget_show (GTK_WIDGET(display_name_label));
	gtk_box_pack_start (GTK_BOX (dn_box), GTK_WIDGET(eb), FALSE, FALSE, 0);
	
	g_object_set_data(G_OBJECT(hbox), PLUGIN_ID_DN_WIDGET, display_name_label);

	g_signal_connect(G_OBJECT(eb), "button-press-event", 
							G_CALLBACK(on_display_name_focus_cb), NULL);
	g_signal_connect(G_OBJECT(eb), "enter-notify-event",
							G_CALLBACK(on_display_name_hover_cb), NULL);
	g_signal_connect(G_OBJECT(eb), "leave-notify-event",
							G_CALLBACK(on_display_name_hover_cb), NULL);


	GTK_WIDGET_SET_FLAGS (display_name_label, GTK_CAN_FOCUS);

	/* Status Button - get the status text from the gtkstatusbox */
	path = gtk_tree_row_reference_get_path(statusbox->active_row);
	if (!gtk_tree_model_get_iter (GTK_TREE_MODEL(statusbox->dropdown_store), &iter, path))
		return;
	gtk_tree_path_free(path);
	gtk_tree_model_get(GTK_TREE_MODEL(statusbox->dropdown_store), &iter,
						0, &type,
						6, &data,
						-1);
	if (type == PIDGIN_STATUS_BOX_TYPE_PRIMITIVE)
		text = g_strdup(purple_primitive_get_name_from_type(GPOINTER_TO_INT(data)));
	if (text == NULL || (!strcmp(text, "")))
		text = "No Status";
	purple_debug_info(PLUGIN_ID, "plugin_load: status from statusbox: %s\n", text);
	
	purple_debug_info(PLUGIN_ID, "insert_personal_bar: Setting up status label\n");
	status = g_string_new(text);
	status = g_string_prepend(status, "(");
	status = g_string_append(status, ")");
	status_button = gtk_button_new();
	gtk_button_set_focus_on_click(GTK_BUTTON(status_button), FALSE);
	gtk_button_set_label(GTK_BUTTON(status_button), status->str);	
	gtk_widget_show (GTK_WIDGET(status_button));
  	gtk_box_pack_start (GTK_BOX (dn_box), GTK_WIDGET(status_button), FALSE, FALSE, 0);
  	gtk_button_set_relief (GTK_BUTTON (status_button), GTK_RELIEF_NONE);
  	gtk_widget_set_name(status_button, "pidgin-personalbar-statusbutton");
	g_object_set_data(G_OBJECT(hbox), PLUGIN_ID_STATUS_LABEL, status_button);
  	g_signal_connect (GTK_BUTTON(status_button), "button-press-event",
					  G_CALLBACK (on_status_button_clicked_cb), NULL);
 	/* We're finished with dn_box, so pack it into the vertical box */
	gtk_box_pack_start (GTK_BOX (vbox), dn_box, FALSE, FALSE, 0);
	GTK_WIDGET_SET_FLAGS (dn_box, GTK_CAN_FOCUS);
	
	/* 
	 * 
	 * Personal Message 
	 *
	 */
	pm_label = gtk_label_new(NULL);
	pm_eb = gtk_event_box_new();
	gtk_widget_show(GTK_WIDGET(pm_eb));
	gtk_container_add(GTK_CONTAINER(pm_eb), GTK_WIDGET(pm_label));
	gtk_event_box_set_above_child(GTK_EVENT_BOX(pm_eb), FALSE);
	gtk_widget_set_events(GTK_WIDGET(pm_eb), GDK_BUTTON_PRESS_MASK);
	//GdkColor color;
	gdk_color_parse ("grey", &color);
	gtk_widget_modify_fg (GTK_WIDGET(pm_eb), GTK_STATE_NORMAL, &color);

	personal_msg = purple_prefs_get_string(pref_personal_msg);
	if (personal_msg == NULL) {
		purple_prefs_set_string(pref_personal_msg, "");
		personal_msg = purple_prefs_get_string(pref_personal_msg);
	}
	/* Get the status box text */
	if (gtkblist != NULL && GTK_IS_WINDOW(gtkblist->window)) {
		purple_debug_info(PLUGIN_ID, "gtkblist is not null and gtkblist->window is a gtk window\n");
		statusbox_text = get_statusbox_text();
	}
	else statusbox_text = "";
	
	/* Compare both personal message pref and status box text. If both
		are empty then set default empty string, or take one over the other if
		it's not empty, or else take the personal message pref */
	if (!strcmp(personal_msg, "") && !strcmp(statusbox_text, "")) {
		purple_debug_info(PLUGIN_ID, "insert_personal_bar: pref_personal_msg and statusbox_text are empty\n");
		markup = g_markup_printf_escaped (MU_PERSONAL_MSG, PERSONAL_MSG_EMPTY);
	}
	else if (!strcmp(personal_msg, "") && strcmp(statusbox_text, "")) {
		purple_debug_info(PLUGIN_ID, "insert_personal_bar: pref_personal_msg empty but statusbox_text has something in it\n");
		purple_prefs_set_string(pref_personal_msg, statusbox_text);
		markup = g_markup_printf_escaped (MU_PERSONAL_MSG, purple_prefs_get_string(pref_personal_msg));
	}
	else if (strcmp(personal_msg, "") && !strcmp(statusbox_text, "")) {
		purple_debug_info(PLUGIN_ID, "insert_personal_bar: pref_personal_msg has something in it (%s) \
												and statusbox_text is empty, setting statusbox with personal msg\n", personal_msg);
		if (!statusbox->imhtml_visible) statusbox->imhtml_visible = TRUE;
		gtk_text_buffer_set_text(GTK_IMHTML(statusbox->imhtml)->text_buffer, personal_msg, -1);
		markup = g_markup_printf_escaped (MU_PERSONAL_MSG, personal_msg);
	}
	else if (strcmp(personal_msg, "") && strcmp(statusbox_text, "")) {
		if (!statusbox->imhtml_visible) statusbox->imhtml_visible = TRUE;
		gtk_text_buffer_set_text(GTK_IMHTML(statusbox->imhtml)->text_buffer, personal_msg, -1);
		markup = g_markup_printf_escaped (MU_PERSONAL_MSG, personal_msg);
	}
	else {
		 purple_debug_error(PLUGIN_ID, "insert_personal_bar: no personal msg markup set!!\n");
	}
	
	/* Set up the personal message label and entry box */
	purple_debug_info(PLUGIN_ID, "insert_personal_bar: Setting up personal message label\n");
	purple_debug_info(PLUGIN_ID, "insert_personal_bar: applying %s as pm markup\n", markup);
	pm_label = gtk_label_new(NULL);
	/* Set a defined size for the label since it gets a -1 by default */
	gtk_widget_set_size_request(GTK_WIDGET(pm_label), purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-50, -1);
	gtk_widget_show(GTK_WIDGET(pm_label));
	gtk_label_set_markup (GTK_LABEL(pm_label), markup);
	gtk_misc_set_alignment(GTK_MISC(pm_label), 0.0f, 1.0f);
#if GTK_CHECK_VERSION(2,6,0)
		g_object_set(G_OBJECT(pm_label), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
#endif
	gtk_widget_set_tooltip_text(GTK_WIDGET(pm_label), purple_prefs_get_string(pref_personal_msg));
	/* Depending on size of buddy list window, set initial size of label */
	gtk_widget_get_size_request(GTK_WIDGET(pm_label), &pm_label_width, &pm_label_height);
	purple_debug_info(PLUGIN_ID, "pm_label_width: %d, blist/width: %d\n", pm_label_width, purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width"));
	if (purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-50 < pm_label_width) 
		gtk_widget_set_size_request(GTK_WIDGET(pm_label), purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-50, -1);
		
	pm_eb = gtk_event_box_new();
	gtk_widget_show(GTK_WIDGET(pm_eb));
	gtk_container_add(GTK_CONTAINER(pm_eb), GTK_WIDGET(pm_label));
	gtk_event_box_set_above_child(GTK_EVENT_BOX(pm_eb), FALSE);
	gtk_widget_set_events(GTK_WIDGET(pm_eb), GDK_BUTTON_PRESS_MASK);
	//gdk_color_parse ("grey", &color);
	gdk_color_parse ("#eaeaea", &color);
	gtk_widget_modify_fg(GTK_WIDGET(pm_eb), GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(GTK_WIDGET(pm_eb), GTK_STATE_NORMAL, &color);
	g_object_set_data(G_OBJECT(hbox), PLUGIN_ID_PM_LABEL, pm_label);
	gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET(pm_eb), FALSE, FALSE, 0);

	/* Create a personal message entry box and hide it for later use */
	pm_entry = gtk_entry_new ();
	gtk_entry_set_has_frame(GTK_ENTRY(pm_entry), FALSE);
	if (purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-50 < pm_label_width)
		gtk_widget_set_size_request(GTK_WIDGET(pm_entry), purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-50, -1);

	gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(pm_entry), TRUE, TRUE, 0);	
	g_object_set_data(G_OBJECT(hbox), PLUGIN_ID_PM_ENTRY, pm_entry);
	gtk_widget_hide (pm_entry);
	
	g_signal_connect(G_OBJECT(pm_eb), "button-press-event", 
			G_CALLBACK(on_personal_msg_focus_cb), NULL);
	g_signal_connect(G_OBJECT(pm_eb), "enter-notify-event",
			G_CALLBACK(on_personal_msg_hover_cb), NULL);
	g_signal_connect(G_OBJECT(pm_eb), "leave-notify-event",
			G_CALLBACK(on_personal_msg_hover_cb), NULL);
	g_signal_connect (G_OBJECT(pm_entry), "focus-out-event",
			G_CALLBACK (on_personal_entry_focus_out_cb), NULL);
	g_signal_connect (G_OBJECT(pm_entry), "key-release-event",
			G_CALLBACK (on_personal_entry_key_press_cb), NULL);


	gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);

	/* g_signal_connect ((gpointer) widget_display_name, "editing_done",
   						G_CALLBACK (display_name_handler),
                    	NULL);
	*/

}


/* Set the personal message the same as the statusbox message */
void
set_pm_as_sbm() {

}

/* If personal msg stored pref is empty then check statusbox imhtml text
	* and if statusbox_imhtml is not empty then use that as the personal msg.
	* Else if statusbox_imhtml is empty then set stored PM to 
	* default msg '<Type a personal message>' 
	*
	* If personal msg is not empty then set 
	* */
void
check_personal_msg(const char *personal_msg) {
	PidginStatusBox *statusbox;
	GtkTextBuffer *buffer;
	GtkTextIter start, end;
	char *statusbox_imhtml;
	int buffer_count;

	if (!strcmp(personal_msg, "")) {
		statusbox = PIDGIN_STATUS_BOX(pidgin_blist_get_default_gtk_blist()->statusbox);
		buffer = GTK_IMHTML(statusbox->imhtml)->text_buffer;
		buffer_count = gtk_text_buffer_get_char_count(buffer);
		/* Need to check that buffer is not empty, otherwise iter_at_offset crashes plugin */
		if (buffer_count > 0) {
			purple_debug_info(PLUGIN_ID, "check_personal_bar: buffer_count = %i\n", buffer_count);
			gtk_text_buffer_get_start_iter(buffer, &start);
			gtk_text_buffer_get_end_iter(buffer, &end);
			statusbox_imhtml = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
			if (!strcmp(statusbox_imhtml, "")) {
				purple_prefs_set_string(pref_personal_msg, "");
				purple_debug_info(PLUGIN_ID, "check_personal_msg: personal msg is empty and statusbox_imhtml empty, setting pref_personal_msg as empty, setting default PM\n");
			}
			else {
				purple_prefs_set_string(pref_personal_msg, statusbox_imhtml);
				personal_msg = purple_prefs_get_string(pref_personal_msg);
				purple_debug_info(PLUGIN_ID, "check_personal_bar: personal msg empty but statusbox_imhtml not empty, setting it to stored PM: %s\n", personal_msg);
				//gtk_text_buffer_set_text(GTK_IMHTML(statusbox->imhtml)->text_buffer, personal_msg, -1);//strlen(entry));
			}
		}	
	}
	/* If the personal msg is not empty */
	else {

		// if the statusbox imhtml is empty then set it with the stored pref_personal_msg

	}
}

int
num_accounts_signed_in() {
	int i = 0;
	char *id;
	GList *l;
	PurpleAccount *account;

	purple_debug_info(PLUGIN_ID, "num_accounts_signed_in started\n");
	GList *conn_list = purple_accounts_get_all_active();
	for (l = conn_list; l != NULL; l = l->next) {
		account = l->data;
		//purple_debug_info(PLUGIN_ID, "num_accounts_si: account username: %s\n", account->username);
			id = purple_account_get_protocol_id(account);
			if (purple_account_is_connected(account) && 
				(!strcmp(id, "prpl-msn") || !strcmp(id, "prpl-jabber"))) {
				purple_debug_info(PLUGIN_ID, "num_accounts_signed_in: Found prpl-msn, adding 1\n");
				i += 1;
			}
	}	
	return i;
}

/* Callback for when the buddy list is actually created */
void
gtkblist_created_cb(PurpleBuddyList *blist) {
	PidginBuddyList *gtkblist = PIDGIN_BLIST(blist);
	gboolean visible;
	const char *display_name, *personal_msg;

	purple_debug_info(PLUGIN_ID, "gtkblist created_cb\n");
	/* NOTE: Do I need this if statement? */
	if (gtkblist != NULL && GTK_IS_WINDOW(gtkblist->window)) {
		g_object_get(G_OBJECT(gtkblist->window), "visible", &visible, NULL);
	} 
	else {
		visible = FALSE;
	}	

	display_name = purple_prefs_get_string(pref_display_name);
	personal_msg = purple_prefs_get_string(pref_personal_msg);
	purple_debug_info(PLUGIN_ID, "pref_display_name: %s\n", display_name);
	purple_debug_info(PLUGIN_ID, "pref_personal_msg: %s\n", personal_msg);
	
	if (visible) {
		if (purple_prefs_get_bool(pref_hide_status_bar) && status_box_visible(gtkblist)) {
			gtk_widget_hide(gtkblist->statusbox);
		}
		check_personal_msg(personal_msg/*purple_prefs_get_string(pref_personal_msg)*/);
		insert_personal_bar(gtkblist/*, personalbar->display_name, personalbar->status*/);
	}
	else purple_debug_error(PLUGIN_ID, "gtkblist_created_cb: visible=false, something is wrong\n");

	/* If no accounts are connected then grey out personal bar */
	/* NOTE: Need to update this block to check for no personal bar accts connected */
	if (num_accounts_signed_in() < 1) {
		gtk_widget_set_sensitive(get_pb_widget(gtkblist), FALSE);
	}
	/* Else if any pb accts connected then sensitize the personal bar */
	/*else if (0=0){

	}*/

}

/* Callback for when the user's status is updated */
void
update_status_cb(PurpleAccount *account, PurpleStatus *old, PurpleStatus *new) {

	GtkWidget *personal_box;
	GtkButton *status_label;
	GString *status;

	purple_debug_error(PLUGIN_ID, "Status has changed\n");
	purple_debug_info(PLUGIN_ID, "Old status: %s, New Status: %s\n", purple_status_get_name(old), purple_status_get_name(new));

	// Not used (yet): Update status icon
	
	// Update status name 
	PidginBuddyList *gtkblist = PIDGIN_BLIST(purple_get_blist());
	personal_box = get_pb_widget(gtkblist);
	status_label = get_status_label(personal_box);
	status = g_string_new(purple_status_get_name(new));
	status = g_string_prepend(status, "(");
	status = g_string_append(status, ")");
	gtk_button_set_label(status_label, status->str);

	/* Update the personal message as the user may have changed the pidgin statusbox entry */
	// If personalbar pm and statusbox text are different the personalbar PM takes presidence
	//update_psm_label(get_statusbox_text());
	
	/* Note: Update personal message label ?? */
	purple_debug_info(PLUGIN_ID, "update_status_cb: Ended\n");
	
}

void
account_displayname_changed_cb(PurpleAccount *account, PurpleStatus *old, PurpleStatus *new) {
	purple_debug_error(PLUGIN_ID, "Account display name changed\n");

}


void
signed_on_cb(PurpleConnection *gc) {
	const char *id;
	const char *display_name;
	PurpleAccount *account;
	gboolean sensitive;

	purple_debug_info(PLUGIN_ID, "Signed_on_cb\n");
	
	PidginBuddyList *gtkblist = PIDGIN_BLIST(purple_get_blist());
	display_name = purple_prefs_get_string(pref_display_name);
	account = purple_connection_get_account(gc);
	purple_debug_info(PLUGIN_ID, "display_name: %s\n", display_name);

	//if (!g_strcmp0(pb_display_name, "Signing in...")) {
		id = purple_account_get_protocol_id(account);
		/* If account is in list of personal bar accounts */
		if (!strcmp(id, "prpl-msn") || !strcmp(id, "prpl-jabber") || !strcmp(id, "prpl-msn-pecan")) {
			purple_debug_info(PLUGIN_ID, "signed_on_cb, Found %s!\n", id);
			display_name = purple_prefs_get_string(pref_display_name);
			purple_debug_info(PLUGIN_ID, "signed_on_cb: stored display_name: %s\n", display_name);

			/* Set the display name for this account */
			display_name_change_id_cb(gc, display_name);
			/* Set the personal bar as sensitive if insensitive */
			g_object_get(get_pb_widget(gtkblist), "sensitive", &sensitive, NULL);
			if (!sensitive) gtk_widget_set_sensitive(GTK_WIDGET(get_pb_widget(gtkblist)), TRUE);
	
			/* Set the personal message from status line */
			/*PidginStatusBox *statusbox = PIDGIN_STATUS_BOX(pidgin_blist_get_default_gtk_blist()->statusbox);
			gchar *imhtml_text = gtk_imhtml_get_markup(GTK_IMHTML(statusbox->imhtml));
			update_psm_label(imhtml_text);
			*/

		}
		/*else {
			 display_name = "Signing in...";
		}
		*/
	//}
	/*else {
		// Other accounts are signed in so just change 
		// the server's display name of this signed in acct 
		purple_debug_info(PLUGIN_ID, "Account already signed in, not setting pb "
								"display name but updating the display name "
								"for the signed in account\n");
		display_name_change_id_cb(gc,pb_display_name);
	}
	*/

	int num_accts_si = num_accounts_signed_in();
	purple_debug_info(PLUGIN_ID, "Num accts signed in: %d\n", num_accts_si);
	
	/* If this acct is the first acct to have signed in */
	/*if (!g_strcmp0(pb_display_name, "Signing in...") && num_accts_si < 2) {
		purple_debug_info(PLUGIN_ID, "signed_in_cb: Updating display name (%s) from 'Signing in...'\n", display_name);
		
		display_name_change_id_cb(gc, display_name);
		update_display_name(display_name);
		// ** Update status in personal bar!
		PurpleStatus *purple_status = purple_account_get_active_status(account);
		update_status_cb(account, NULL, purple_status);
	*/
		/* For some reason it spaces itself center if you don't do this */
	/*	GtkLabel *pm_label = get_pm_label(get_pb_widget(PIDGIN_BLIST(purple_get_blist())));
		gtk_misc_set_alignment(GTK_MISC(pm_label), 0.0f, 1.0f); 
	*/
		/* Set the personal message from status line */
	/*	PidginStatusBox *statusbox = PIDGIN_STATUS_BOX(pidgin_blist_get_default_gtk_blist()->statusbox);
		gchar *imhtml_text = gtk_imhtml_get_markup(GTK_IMHTML(statusbox->imhtml));
		update_psm_label(imhtml_text);
	}
	else {
		purple_debug_info(PLUGIN_ID, "signed_on_cb: display_name not 'Signing in...' and num_accts_si > 2\n");
	}
	*/
	purple_debug_info(PLUGIN_ID, "end of siged_in_cb\n");
}


void
signing_on_cb(PurpleConnection *gc) {
	/*GList *l;
	PurpleAccount *account;
	char *id;
	// Check if any accounts already signed in
	gboolean connected = FALSE; 
	GList *conn_list = purple_connections_get_all();
	for (l = conn_list; l != NULL; l = l->next) {
		account = purple_connection_get_account (l->data);
		id = purple_account_get_protocol_id(account);
		if (purple_account_is_connected(account) && !g_strcmp0(id, "prpl-msn")) {
			connected = TRUE;
			break;
		}
	}
	*/
	/* If another account is already connected don't change the display name*/
	/*if (connected) {

	}
	*/
	/* At this moment all accounts are offline, so show Signing in... */
	/*else {
		char *entry = "Signing in...";
		char *markup;

		PidginBuddyList *gtkblist = PIDGIN_BLIST(purple_get_blist());
		GtkLabel *display_name_label = get_dn_label(get_pb_widget(gtkblist));
    	markup = g_markup_printf_escaped (MU_SIGNING_IN, entry);
	   gtk_label_set_markup (GTK_LABEL(display_name_label), markup);

	*/
}

void
signing_off_cb(PurpleConnection *gc) {
	
	/* Check if all personal bar accts are signed off
	 * 	If so then set personal bar as insensitive
	 */
}


/* Preference callback for hide/show the status bar */
void
pref_status_bar_cb(const char *pref, PurplePrefType type, gpointer val, gpointer user_data) {
	PurpleBuddyList *blist = purple_get_blist();
	PidginBuddyList *gtkblist = PIDGIN_BLIST(blist);

	if (purple_prefs_get_bool(pref) && status_box_visible(gtkblist)) {
		gtk_widget_hide(gtkblist->statusbox); 
	}
	else {
		gtk_widget_show(gtkblist->statusbox);
	}
}

void
pref_blist_width_cb(const char *pref, PurplePrefType type, gpointer val, gpointer user_data) {
	
	// Need to get hbox and pm_label and put in function below
	// If pm_label smaller than window size then add ellipisize and update width
	// Also change pm_entry box
	//gtk_widget_set_size_request(hbox, purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-12, -1);
	gint pm_label_width = 0, pm_label_height = 0;
	PidginBuddyList *gtkblist = PIDGIN_BLIST(purple_get_blist());
	GtkLabel *pm_label = get_pm_label(get_pb_widget(gtkblist));
	GtkEntry *pm_entry = get_pm_entry(get_pb_widget(gtkblist));

	gtk_widget_get_size_request(GTK_WIDGET(pm_label), &pm_label_width, &pm_label_height);
	//purple_debug_info(PLUGIN_ID, "pm_label_width: %d, buddylist width: %d\n", pm_label_width, purple_prefs_get_int(pref)-50);
	gtk_widget_set_size_request(GTK_WIDGET(pm_label), purple_prefs_get_int(pref)-55, -1);
	gtk_widget_set_size_request(GTK_WIDGET(pm_entry), purple_prefs_get_int(pref)-55, -1);
	if (pm_label_width > purple_prefs_get_int(pref)-50) 
		gtk_label_set_ellipsize(pm_label, PANGO_ELLIPSIZE_NONE);
	else 
		gtk_label_set_ellipsize(pm_label, PANGO_ELLIPSIZE_END);
}

static gboolean
plugin_load(PurplePlugin *plugin) {
	PidginBuddyList *gtkblist = PIDGIN_BLIST(purple_get_blist());
	const char *display_name = "", *status = "Offline", *personal_msg;//, *status_id;

	
	/* Get stored display name */
	display_name = purple_prefs_get_string(pref_display_name);
	/* Get stored personal message */
	personal_msg = purple_prefs_get_string(pref_personal_msg);
	purple_debug_info(PLUGIN_ID, "plugin_load: pref_display_name: %s\n", display_name);
	purple_debug_info(PLUGIN_ID, "plugin_load: pref_personal_msg: %s\n", personal_msg);

	if (!strcmp(display_name, "")) { //display_name == NULL || display_name == "") {
		purple_debug_info(PLUGIN_ID, "display_name is null or empty\n");
		//purple_prefs_set_string(pref_display_name, "<Display Name>");
		//display_name = purple_prefs_get_string(pref_display_name);
	}
	else {
		purple_debug_info(PLUGIN_ID, "plugin_load: Stored display pref: %s\n", display_name);
	}

	if (status == NULL || !strcmp(status, "")) {
		status = "Offline";
	}

	/* If the gtk buddy list is already created */
	if (gtkblist != NULL && GTK_IS_WINDOW(gtkblist->window)) {
		purple_debug_info(PLUGIN_ID, "gtkblist CREATED\n");
		purple_debug_info(PLUGIN_ID, "plugin_load: display_name: %s\n", display_name);
		purple_debug_info(PLUGIN_ID, "plugin_load: status: %s\n", status);

		/* Check for empty stored personal msg and pidgin statusbox imhtml */
		check_personal_msg(personal_msg);		

		// ****Note: And check status (when offline) that status = Offline. This part isn't working
		insert_personal_bar(gtkblist/*, display_name, status*/);
	}
	else { 
		// gtkblist is not created yet
		purple_debug_info(PLUGIN_ID, "gtkblist not created yet, loading func in cb\n");
		purple_signal_connect(pidgin_blist_get_handle(), "gtkblist-created", plugin, PURPLE_CALLBACK(gtkblist_created_cb), NULL);
	}

	/* Connect pref callbacks */
	purple_prefs_connect_callback(plugin, pref_hide_status_bar, (PurplePrefCallback)pref_status_bar_cb, NULL);	
	purple_prefs_connect_callback(plugin, pref_blist_width, (PurplePrefCallback)pref_blist_width_cb, NULL);

	/* Callbacks */
	purple_signal_connect(purple_accounts_get_handle(), "account-status-changed", plugin, PURPLE_CALLBACK(update_status_cb), NULL);
	purple_signal_connect(purple_connections_get_handle(), "signed-on", plugin, PURPLE_CALLBACK(signed_on_cb), NULL);
	purple_signal_connect(purple_connections_get_handle(), "signing-on", plugin, PURPLE_CALLBACK(signing_on_cb), NULL);
	purple_signal_connect(purple_connections_get_handle(), "signing-off",  plugin, PURPLE_CALLBACK(signing_off_cb), NULL);
	//purple_signal_connect(purple_accounts_get_handle(), "account-displayname-changed", plugin, PURPLE_CALLBACK(account_displayname_changed_cb), NULL);

	/* Widget Callbacks */

	/* If pref_hide_status_bar is TRUE then hide the status bar */
	if (purple_prefs_get_bool(pref_hide_status_bar) && status_box_visible(gtkblist)) {
		gtk_widget_hide(gtkblist->statusbox);
	}

	/* If all (personal bar) accounts are disabled then grey out personal bar */
	if (num_accounts_signed_in() < 1) {
		purple_debug_info(PLUGIN_ID, "Sensitive\n");
		gtk_widget_set_sensitive(GTK_WIDGET(get_pb_widget(gtkblist)), FALSE);
	}

	return TRUE;
}

void 
remove_personal_bar(PidginBuddyList *gtkblist) {
	GtkWidget *personalbar;

	purple_debug_info(PLUGIN_ID, "Destroying widget\n");
	personalbar = get_pb_widget(gtkblist);
	if (personalbar != NULL) gtk_widget_destroy(personalbar);
}



static gboolean
plugin_unload(PurplePlugin *plugin) {
	PidginBuddyList *gtkblist = PIDGIN_BLIST(purple_get_blist());

	/* Check if statusbox is invisible, if so, show it on unload */
	gboolean visible = status_box_visible(gtkblist);
	if (!visible) gtk_widget_show(gtkblist->statusbox);

	/* Disconnect all the prefs callbacks */
	purple_prefs_disconnect_by_handle(plugin);
	remove_personal_bar(gtkblist);
	
	return TRUE;
}

static GtkWidget* get_config_frame(PurplePlugin *plugin) {
	GtkWidget *pw;

	/* Main pref window widget */
	pw = gtk_vbox_new(FALSE, 6);
	pidgin_prefs_checkbox("Hide status box", pref_hide_status_bar, pw);

	gtk_widget_show_all(pw);
	return pw;
}

static PidginPluginUiInfo ui_info =
{
	get_config_frame,   /* UI config frame */
	0                   /* page_num */
};

static PurplePluginInfo info =
{
	PURPLE_PLUGIN_MAGIC,
	PURPLE_MAJOR_VERSION,
	PURPLE_MINOR_VERSION,
	PURPLE_PLUGIN_STANDARD,
	PIDGIN_PLUGIN_TYPE,
	0,
	NULL,
	PURPLE_PRIORITY_DEFAULT,
	PLUGIN_ID,
	PLUGIN_NAME, // Plugin name
	PLUGIN_VERSION,

	"Adds a personal bar at the top of the buddy list.", // Plugin Summary
	"Long description of personal bar.", // Long desc
	PLUGIN_AUTHOR,
	PLUGIN_WEBSITE,
	plugin_load,
	plugin_unload,
	NULL, //plugin_destroy
	&ui_info,
	NULL, // For plugin actions
	NULL, // This and next three NULLs for 'future use'
	NULL
};

static void
init_plugin(PurplePlugin *plugin) {

	purple_prefs_add_none("/plugins/gtk/charding");
	purple_prefs_add_none("/plugins/gtk/charding/personalbar");
	purple_prefs_add_bool(pref_hide_status_bar, FALSE);
	purple_prefs_add_string(pref_display_name, "");
	purple_prefs_add_string(pref_personal_msg, "");

}

PURPLE_INIT_PLUGIN(personalbar, init_plugin, info)
